/**
 * 所有不需要鉴权的业务接口
 * 主要是游戏基础信息
 */
const Router = require('@koa/router');
const {
  PlayableClass,
  PlayableRace,
  PlayableSpec,
  MythicKeyStoneAffix: Affix,
  MythicKeystoneDungeon: Dungeon,
  JournalInstance: Journal,
  Spell,
  Item,
} = require('../../db/schemas')

const { Language } = require('../../env');
const { genResponse, replaceRoot, pipeline$match, toString, condNull, pipelineMedia } = require('../../utils');
const router = new Router({ prefix: '/public' })

router.get('/affix/:id', async (ctx) => {
  const results = await Affix.aggregate([
    pipeline$match(ctx.params.id),
    {
      $lookup: {
        from: 'mythic_keystone_affix_media',
        localField: 'id',
        foreignField: 'id',
        as: 'ref_media'
      }
    },
    replaceRoot('ref_media'),
    {
      $addFields: {
        media: {
          $arrayElemAt: ['$assets.value', 0]
        }
      }
    },
    {
      $project: {
        _id: 0,
        id: 1,
        name: `$name.${Language}`,
        description: `$description.${Language}`,
        media: 1,
      }
    }
  ])
  ctx.body = genResponse(true, results)
})

// 通用聚合操作
const pipeline = [
  {
    $lookup: {
      from: 'journal_instance_media',
      let: { journal_id: '$media.id' },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: ['$id', '$$journal_id']
            }
          }
        }
      ],
      as: 'ref_media'
    }
  },
  { $unwind: '$ref_media' },
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: ['$$ROOT', '$ref_media']
      }
    }
  }
]
router.get('/dungeons', async (ctx) => {
  const ids = [247, 370, 382, 499, 500, 504, 506, 525]
  const results = await Dungeon.aggregate([
    {
      $match: { id: { $in: ids } },
    },
    {
      $lookup: {
        from: 'journal_instance',
        let: { dungeon_id: '$dungeon.id' },
        pipeline: [
          {
            $match: {
              $expr: {
                $eq: ['$id', '$$dungeon_id']
              }
            }
          }
        ],
        as: 'dungeon'
      }
    },
    { $unwind: '$dungeon' },
    {
      $replaceRoot: {
        newRoot: {
          $mergeObjects: ['$$ROOT', '$dungeon']
        }
      }
    },
    ...pipeline,
    {
      $project: {
        _id: 0,
        id: 1,
        name: `$name.${Language}`,
        description: `$description.${Language}`,
        texture: {
          $arrayElemAt: ['$assets.value', 0]
        },
      }
    }
  ])

  ctx.body = genResponse(true, results)
})

router.get('/journal-instance/:id', async (ctx) => {
  const results = await Journal.aggregate([
    {
      $match: { id: Number(ctx.params.id) },
    },
    ...pipeline,
    {
      $project: {
        _id: 0,
        id: 1,
        name: `$name.${Language}`,
        description: `$description.${Language}`,
        texture: {
          $arrayElemAt: ['$assets.value', 0]
        },
        encounters: {
          $map: {
            input: '$encounters',
            as: 'encounter',
            in: {
              id: '$$encounter.id',
              name: `$$encounter.name.${Language}`
            }
          }
        }
      }
    }
  ])

  if (results.length === 1) {
    ctx.body = genResponse(true, results[0])
  } else {
    ctx.body = genResponse(true, results)
  }
})

router.get('/spell/:id', async (ctx) => {
  const results = await Spell.aggregate([
    pipeline$match(ctx.params.id),
    {
      $lookup: {
        from: 'spell_media',
        localField: 'id',
        foreignField: 'id',
        as: 'ref_media'
      }
    },
    replaceRoot('ref_media'),
    {
      $addFields: {
        media: {
          $arrayElemAt: ['$assets.value', 0]
        }
      }
    },
    {
      $project: {
        _id: 0,
        id: 1,
        name: `$name.${Language}`,
        description: `$description.${Language}`,
        media: 1,
      }
    }
  ])
  ctx.body = genResponse(true, results)
})

router.get('/item/:id', async (ctx) => {
  const results = await Item.aggregate([
    pipeline$match(ctx.params.id),
    {
      $lookup: {
        from: 'item_media',
        localField: 'id',
        foreignField: 'id',
        as: 'ref_media'
      }
    },
    replaceRoot('ref_media'),
    {
      $addFields: {
        media: {
          $arrayElemAt: ['$assets.value', 0]
        }
      }
    },
    {
      $project: {
        _id: 0,
        id: 1,
        media: 1,
        name: `$name.${Language}`,
        level: `$preview_item.level.display_string.${Language}`, // 物品等级
        // quality: `$preview_item.quality.name.${Language}`,
        // item_subclass: `$preview_item.item_subclass.name.${Language}`,
        // 主类型，如：武器
        item_class: {
          id: `$item_class.id`,
          name: `$item_class.name.${Language}`,
        },
        // 护甲（护甲类才有）
        armor: condNull('$preview_item.armor', {
          display_string: `$preview_item.armor.display.display_string.${Language}`,
          color: {
            $concat: [
              'rgba(',
              toString('$preview_item.armor.display.color.r'),
              ',',
              toString('$preview_item.armor.display.color.g'),
              ',',
              toString('$preview_item.armor.display.color.b'),
              ',',
              toString('$preview_item.armor.display.color.a'),
              ')'
            ]
          }
        }),
        inventory_type: `$preview_item.inventory_type.name.${Language}`, // 部位，如：双手
        // 次类型，如：法杖
        item_subclass: {
          id: `$item_subclass.id`,
          name: `$item_subclass.name.${Language}`,
        },
        // 伤害（武器才有）
        weapon: condNull('$preview_item.weapon', {
          damage: `$preview_item.weapon.damage.display_string.${Language}`,
          attack_speed: `$preview_item.weapon.attack_speed.display_string.${Language}`,
          dps: `$preview_item.weapon.dps.display_string.${Language}`
        }),
        // binding: `$preview_item.binding.name.${Language}`,
        // 属性
        stats: {
          $map: {
            input: '$preview_item.stats',
            as: 'stat',
            in: {
              display_string: `$$stat.display.display_string.${Language}`,
              color: {
                $concat: [
                  'rgba(',
                  toString('$$stat.display.color.r'),
                  ',',
                  toString('$$stat.display.color.g'),
                  ',',
                  toString('$$stat.display.color.b'),
                  ',',
                  toString('$$stat.display.color.a'),
                  ')'
                ]
              }
            }
          }
        },
        durability: `$preview_item.durability.display_string.${Language}`, // 耐久
        // 装备特效
        description: {
          $map: {
            input: '$preview_item.spells',
            as: 's',
            in: `$$s.description.${Language}`
          }
        },
        sell_price: {
          $concat: [
            `$preview_item.sell_price.display_strings.header.${Language}`,
            `$preview_item.sell_price.display_strings.silver.${Language}`,
            '银',
            `$preview_item.sell_price.display_strings.copper.${Language}`,
            '铜'
          ]
        },
      }
    }
  ])
  ctx.body = genResponse(true, results)
})

router.get('/class', async (ctx) => {
  const results = await PlayableClass.aggregate([
    ...pipelineMedia({ from: 'playable_class_media' }),
    {
      $project: {
        id: 1,
        texture: { $arrayElemAt: ["$texture.assets.value", 0] },
        name: `$name.${Language}`,
        power_type: `$power_type.name.${Language}`,
        specializations: {
          $map: {
            input: '$specializations',
            as: 'spec',
            in: {
              id: '$$spec.id',
              name: `$$spec.name.${Language}`
            }
          }
        }
      }
    },
  ])
  ctx.body = genResponse(true, results)
})

router.get('/race', async (ctx) => {
  const results = await PlayableRace.aggregate([
    {
      $project: {
        id: 1,
        name: `$name.${Language}`,
        faction: `$faction.type`,
        is_allied_race: 1,
        playable_classes: {
          $map: {
            input: '$playable_classes',
            as: 'pc',
            in: '$$pc.id'
          }
        }
      }
    },
  ])
  ctx.body = genResponse(true, results)
})

router.get('/spec', async (ctx) => {
  const ids = ctx.query.ids.split(',').map(id => parseInt(id))
  const results = await PlayableSpec.aggregate([
    {
      $match: { id: { $in: ids } },
    },
    ...pipelineMedia({ from: 'playable_spec_media' }),
    {
      $project: {
        id: 1,
        name: `$name.${Language}`,
        texture: { $arrayElemAt: ["$texture.assets.value", 0] },
        description: `$gender_description.male.${Language}`,
        role: `$role.name.${Language}`,
        power_type: `$power_type.name.${Language}`,
        primary_stat_type: `$primary_stat_type.name.${Language}`,
      }
    },
  ])
  ctx.body = genResponse(true, results)
})

module.exports = router